#include "stdafx.h"
#include "PowerTreeNode.h"
#include "exceptions.h"
#include "ComputationalTreeNodeVisitor.h"

using CollabRC::Bot::AI::PowerTreeNode;
PowerTreeNode::Factory PowerTreeNode::factory;

/**
 * @brief Creates a new PowerTreeNode to operate on the specified two branches
 * @param lhs the left hand side branch which will be used as the base
 * @param rhs the right hand side branch which will be used as the exponent
 */
PowerTreeNode::PowerTreeNode(const ComputationalTreeNode& lhs, const ComputationalTreeNode& rhs):
    OperationTreeNode(lhs, rhs)
{
}

/**
 * @brief Copy constructor for PowerTreeNode
 *
 * This copy constructor actually accepts any OperationTreeNode
 * @param copy the object from which to copy
 */
PowerTreeNode::PowerTreeNode(const CollabRC::Bot::AI::OperationTreeNode& copy):OperationTreeNode(copy)
{
}

/** @brief Destroys this PowerTreeNode and all associated resources */
PowerTreeNode::~PowerTreeNode(void)
{
}

/** {@inheritDoc} */
float PowerTreeNode::PerformOperation(float lhs, float rhs) const
{
    // Raising a negative value to a fractional power is illegal (e.g., sqrt(-1))
    if (lhs < 0 && rhs != static_cast<int>(rhs))
        throw IllegalOperationException("Attempt to raise a negative value to a fractional power");

    return static_cast<float>(std::pow(lhs, rhs));
}

/** {@inheritDoc} */
CollabRC::Bot::AI::ComputationalTreeNode* PowerTreeNode::Clone() const
{
    return new PowerTreeNode(*this);
}

/** {@inheritDoc} */
CollabRC::Bot::AI::ComputationalTreeNode* PowerTreeNode::Factory::Instantiate(const ComputationalTreeNode &lhs, const ComputationalTreeNode &rhs) const
{
    return new PowerTreeNode(lhs, rhs);
}

void PowerTreeNode::Accept(CollabRC::Bot::AI::ComputationalTreeNodeVisitor& visitor)
{
    visitor.Visit(*this);
}
